using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using System.Threading;
using System.Diagnostics;
using System.Collections;
using BrainTechLLC;
using System.Runtime.Serialization;
using System.Runtime.Versioning;
using System.Net.Sockets;

namespace Mud.EmlenMudMain
{
#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class BanData
    {
        public BanData() { }
        private string name = "";		/* Numeric site ban */

        public string NameOfSite
        {
            get { return name; }
            set { name = value; }
        }
        private bool newbie = false;	/* Newbie banned?  If so, people from this site
			   must go through email validation to play! */


        public bool Newbie
        {
            get { return newbie; }
            set { newbie = value; }
        }

        public static bool Load(int inVersion)
        {
            if (SerializeBanIn(inVersion) == false)
            {
                EmlenMud.Oldschool.load_bansites_old_format();
                if (MiscConstants.DataStorageFormat == DataStorageFormatTypes.CompressedSerialization)
                    BanData.Save(inVersion);
            }
            return true;
        }

        public static bool Save(int outVersion)
        {
            return SerializeBanOut(outVersion);
        }

        public static bool SerializeBanIn(int inVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(BanData).Name.ToString() + inVersion.ToString();
            Object o = SerializationHelper.SerializeObjectIn(szFName);
            if (o == null) return false;
            EmlenMud.WorldTemplates.ban_list.Clear();
            if (o is Hashtable)
            {
                Hashtable ht = (Hashtable)o;
                foreach (DictionaryEntry de in ht)
                {
                    BanData ban = (BanData)de.Value;
                    //ban.AssignEmlenMud(EmlenMud);
                    EmlenMud.WorldTemplates.ban_list.Add((string)de.Key, ban);
                }
                return true;
            }
            return false;
#else
            return true;
#endif
        }

        public static bool SerializeBanOut(int outVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(BanData).Name.ToString() + outVersion.ToString();
            return SerializationHelper.SerializeObjectOut(EmlenMud.WorldTemplates.ban_list, szFName, true);
#else
            return true;
#endif
        }

    }


#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class WeatherData : IWeatherData
    {
        public WeatherData() { }
        private int mmhg;		/* Mercury mm */

        public int Mmhg
        {
            get { return mmhg; }
            set { mmhg = value; }
        }
        private int temperature;	/* Farenheight temp */

        public int Temperature
        {
            get { return temperature; }
            set { temperature = value; }
        }
        private int change;		/* Last change */

        public int Change
        {
            get { return change; }
            set { change = value; }
        }
        private SkyWeather sky;		/* Sky value */

        public SkyWeather Sky
        {
            get { return sky; }
            set { sky = value; }
        }
        private TimeOfDayType sunlight;	/* Sunlight value */

        public TimeOfDayType Sunlight
        {
            get { return sunlight; }
            set { sunlight = value; }
        }
        private int winddir;	/* Wind direction */

        public int Winddir
        {
            get { return winddir; }
            set { winddir = value; }
        }
        private int windspeed;	/* Wind speed */

        public int Windspeed
        {
            get { return windspeed; }
            set { windspeed = value; }
        }
    }


#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class TimeInfoData :
#if NO_SILVERLIGHT
 ICloneable,
#endif
 IComparable<TimeInfoData>, ITimeInfoData
    {

        public TimeInfoData() { }
        private DateTime dtInternal;

        public DateTime DtInternal
        {
            get { return dtInternal; }
            set { dtInternal = value; }
        }

        public void SetTimeInfo(DateTime dt) { dtInternal = dt; }

        public TimeSpan ElapsedTime
        {
            get { return EmlenMud.DynamicWorld.CurrentTime.dtInternal.Subtract(dtInternal); }
        }

        public TimeSpan TimeBetween(TimeInfoData firstEventTime, TimeInfoData secondEventTime)
        {
            return secondEventTime.dtInternal.Subtract(firstEventTime.dtInternal);
        }


        public string this[TimeElements timeElement]
        {
            get
            {
                switch (timeElement)
                {
                    case TimeElements.year:
                        return dtInternal.Year.ToString();
                    case TimeElements.month:
                        {
#if NO_SILVERLIGHT
                            string sz = Enum.Format(typeof(MonthNames), (MonthNames)(dtInternal.Month), "G");
#else
                            string sz = ((MonthNames)dtInternal.Month).ToString();
#endif
                            sz.Replace('_', ' ');
                            return sz;
                        }
                    case TimeElements.date:
                        return StaticHelpers.NumberToOrderString(dtInternal.Day);
                    case TimeElements.hour:
                        return StaticHelpers.NumberToOrderString(Convert.ToInt32(dtInternal.ToString("H")));
                    case TimeElements.dayofweek:
                        {
#if NO_SILVERLIGHT
                            string sz = Enum.Format(typeof(DaysOftheWeek), (DaysOftheWeek)((int)(dtInternal.DayOfWeek)), "G");
#else
                            string sz = ((DaysOftheWeek)dtInternal.DayOfWeek).ToString();
#endif
                            sz.Replace('_', ' ');
                            return sz;
                        }
                    case TimeElements.minute:
                        return StaticHelpers.NumberToOrderString(dtInternal.Minute);
                    case TimeElements.second:
                        return StaticHelpers.NumberToOrderString(dtInternal.Second);
                    case TimeElements.millisecond:
                        return StaticHelpers.NumberToOrderString(dtInternal.Millisecond);
                    default:
                        return timeElement.ToString();
                }
            }
        }

        public DateTime dt
        {
            get { return dtInternal; }
        }

        public int CompareTo(TimeInfoData other)
        {
            return dtInternal.CompareTo(other.dtInternal);
        }

        public Object Clone()
        {
            TimeInfoData timeData = new TimeInfoData();
            timeData.dtInternal = this.dtInternal;
            return timeData;
        }
    }

#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class TopTenData : ITopTenData
    {

        public TopTenData() { }
        private string[] topten_name = new string[10];

        public string[] Topten_name
        {
            get { return topten_name; }
            set { topten_name = value; }
        }
        private int[] topten_warpoints = new int[10];

        public int[] Topten_warpoints
        {
            get { return topten_warpoints; }
            set { topten_warpoints = value; }
        }
        private bool[] topten_good = new bool[10];

        public bool[] Topten_good
        {
            get { return topten_good; }
            set { topten_good = value; }
        }

        public static bool Load(int inVersion)
        {
            if (TopTenData.SerializeIn(inVersion) == false)
            {
                EmlenMud.Oldschool.load_topten_old_format();
                if (MiscConstants.DataStorageFormat == DataStorageFormatTypes.CompressedSerialization) TopTenData.Save(inVersion);
            }
            return true;
        }

        public static bool Save(int outVersion)
        {
            return TopTenData.SerializeOut(outVersion);
        }

        public static bool SerializeIn(int inVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(TopTenData).Name.ToString() + inVersion.ToString();
            Object o = SerializationHelper.SerializeObjectIn(szFName);
            if (o == null) return false;
            if (o is TopTenData)
            {
                TopTenData topten = (TopTenData)o;
                //topten.AssignEmlenMud(EmlenMud);
                EmlenMud.WorldTemplates.topten = topten;
                return true;
            }
            return false;
#else 
            return true;
#endif
        }

        public static bool SerializeOut(int outVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(TopTenData).Name.ToString() + outVersion.ToString();
            return SerializationHelper.SerializeObjectOut(EmlenMud.WorldTemplates.topten, szFName, true);
#else 
            return true;
#endif
        }

    }

#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class RatingData : IRatingData
    {
        public RatingData() { }
        private string[] rating_name = new string[10];

        public string[] Rating_name
        {
            get { return rating_name; }
            set { rating_name = value; }
        }
        private int[] rating_rating = new int[10];

        public int[] Rating_rating
        {
            get { return rating_rating; }
            set { rating_rating = value; }
        }
        private bool[] rating_good = new bool[10];

        public bool[] Rating_good
        {
            get { return rating_good; }
            set { rating_good = value; }
        }

        public static bool Load(int inVersion)
        {
            if (RatingData.SerializeIn(inVersion) == false)
            {
                EmlenMud.Oldschool.load_rating_old_format();
                if (MiscConstants.DataStorageFormat == DataStorageFormatTypes.CompressedSerialization) RatingData.Save(inVersion);
            }
            return true;
        }

        public static bool Save(int outVersion)
        {
            return RatingData.SerializeOut(outVersion);
        }

        public static bool SerializeIn(int inVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(RatingData).Name.ToString() + inVersion.ToString();
            Object o = SerializationHelper.SerializeObjectIn(szFName);
            if (o == null) return false;
            if (o is RatingData)
            {
                RatingData rating = (RatingData)o;
                //rating.AssignEmlenMud(EmlenMud);
                EmlenMud.WorldTemplates.ratings = rating;
                return true;
            }
            return false;
#else 
            return true;
#endif
        }

        public static bool SerializeOut(int outVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(RatingData).Name.ToString() + outVersion.ToString();
            return SerializationHelper.SerializeObjectOut(EmlenMud.WorldTemplates.ratings, szFName, true);
#else 
            return true;
#endif
        }

    }

#if NO_SILVERLIGHT
    [Serializable]
#endif
    public class LimitedItemsData : ILimitedItemsData
    {

        public LimitedItemsData() { }

        private Dictionary<long, int> limited_array = new Dictionary<long, int>();

        public Dictionary<long, int> Limited_array
        {
            get { return limited_array; }
            set { limited_array = value; }
        }

        public static bool Load(int inVersion)
        {
            if (LimitedItemsData.SerializeIn(inVersion) == false)
            {
                for (int i = 0; i < 10000; i++)
                {
                    EmlenMud.Oldschool.load_limited_old_format(i);
                }
                LimitedItemsData.Save(inVersion);
            }
            return true;
        }

        public static bool Save(int outVersion)
        {
            return LimitedItemsData.SerializeOut(outVersion);
        }

        public static bool SerializeIn(int inVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(LimitedItemsData).Name.ToString() + inVersion.ToString();
            Object o = SerializationHelper.SerializeObjectIn(szFName);
            if (o == null) return false;
            if (o is LimitedItemsData)
            {
                LimitedItemsData limiteditemsd = (LimitedItemsData)o;
                //limiteditemsd.AssignEmlenMud(EmlenMud);
                EmlenMud.WorldTemplates.LimitedItems = limiteditemsd;
                return true;
            }
            return false;
#else 
            return true;
#endif
        }

        public static bool SerializeOut(int outVersion)
        {
#if NO_SILVERLIGHT
            string szFName = EmlenMud.HostPathnameToMudDirectory + "\\" + MiscConstants.DataFileDirectory + "\\" + typeof(LimitedItemsData).Name.ToString() + outVersion.ToString();
            return SerializationHelper.SerializeObjectOut(EmlenMud.WorldTemplates.LimitedItems, szFName, true);
#else 
            return true;
#endif
        }

    }


    [Serializable]
    public class ChannelData : IChannelData
    {
        public ChannelData() { }
        private bool clan;		/* Clan channel? */

        public bool Clan
        {
            get { return clan; }
            set { clan = value; }
        }
        private bool sect;		/* Sect channel? */

        public bool Sect
        {
            get { return sect; }
            set { sect = value; }
        }
        private string channel_name;	/* Channel name */

        public string Channel_name
        {
            get { return channel_name; }
            set { channel_name = value; }
        }
        private List<string> commands = new List<string>();	/* Commands to use this channel */

        public List<string> Commands
        {
            get { return commands; }
            set { commands = value; }
        }
        private int level;		/* MinimumLevelToViewTopic to use this channel */

        public int Level
        {
            get { return level; }
            set { level = value; }
        }
        private int to_level;	/* Channel is seen by all higher than this level */

        public int To_level
        {
            get { return to_level; }
            set { to_level = value; }
        }
        private string color;	/* Color of this channel for newbies */

        public string Color
        {
            get { return color; }
            set { color = value; }
        }
        private int moves;		/* Takes this amount of moves to use channel */

        public int Moves
        {
            get { return moves; }
            set { moves = value; }
        }
        private ChannelTo to_align;		/* 1 = same align as you  2 = good  3 = evil
				   4 = both aligns */


        public ChannelTo To_align
        {
            get { return to_align; }
            set { to_align = value; }
        }

    }

    [Serializable]
    public class ColorData
    {

        private string code;

        public string Code
        {
            get { return code; }
            set { code = value; }
        }
        private string act_code;

        public string Act_code
        {
            get { return act_code; }
            set { act_code = value; }
        }
        private string name;

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
        private int number;

        public int Number
        {
            get { return number; }
            set { number = value; }
        }
    }

    [Serializable]
    public class MaterialData
    {
        private string materialname;

        public string Materialname
        {
            get { return materialname; }
            set { materialname = value; }
        }
        private int weight;  /* /4 for body, /5 for legs, /6 for arms, /7 for head,
		     /7 for feet, /9 for gloves */

        public int Weight
        {
            get { return weight; }
            set { weight = value; }
        }
        private int strength; /* the naturalArmor durability/hp value */

        public int Strength
        {
            get { return strength; }
            set { strength = value; }
        }
        private int armor;

        public int Armor
        {
            get { return armor; }
            set { armor = value; }
        }
        private int a_slash; /* This armorval for slash */

        public int A_slash
        {
            get { return a_slash; }
            set { a_slash = value; }
        }
        private int a_pierce;

        public int A_pierce
        {
            get { return a_pierce; }
            set { a_pierce = value; }
        }
        private int a_pound;

        public int A_pound
        {
            get { return a_pound; }
            set { a_pound = value; }
        }
        private int pointcost; /* amount of creation points it costs */

        public int Pointcost
        {
            get { return pointcost; }
            set { pointcost = value; }
        }
        private string desc;

        public string Desc
        {
            get { return desc; }
            set { desc = value; }
        }
        private int min_level;

        public int Min_level
        {
            get { return min_level; }
            set { min_level = value; }
        }
        private bool disabled;

        public bool Disabled
        {
            get { return disabled; }
            set { disabled = value; }
        }
        private bool s_bplate_etc;

        public bool S_bplate_etc
        {
            get { return s_bplate_etc; }
            set { s_bplate_etc = value; }
        }
        private int initflags;

        public int Initflags
        {
            get { return initflags; }
            set { initflags = value; }
        }
        private int cost;	/* /3 for body, /5 for legs, /5 for arms, /6 for head
		   /7 for feet, /8 for gloves, etc */


        public int Cost
        {
            get { return cost; }
            set { cost = value; }
        }

    }

    [Serializable]
    public class AttackTypeData
    {



        public AttackTypeData() { }
        private string attacktypename;

        public string Attacktypename
        {
            get { return attacktypename; }
            set { attacktypename = value; }
        }
        private int hit_type;

        public int Hit_type
        {
            get { return hit_type; }
            set { hit_type = value; }
        }
    }

    [Serializable]
    public class liq_type
    {
        public liq_type() { }
        private string liq_name;

        public string Liq_name
        {
            get { return liq_name; }
            set { liq_name = value; }
        }
        private string liq_color;

        public string Liq_color
        {
            get { return liq_color; }
            set { liq_color = value; }
        }
        private int[] liq_effect = new int[3];	/* 1=drunk 2=food 3=thirst */

        public int[] Liq_effect
        {
            get { return liq_effect; }
            set { liq_effect = value; }
        }
    }

    [Serializable]
    [DataContract]
    public class ExtraDescriptionData 
    {
        public ExtraDescriptionData() { }
        private string description;		/* The actual extra description */

        public string Description
        {
            get { return description; }
            set { description = value; }
        }
        private string keyword;		/* KeywordList list to see this description */

        public string Keyword
        {
            get { return keyword; }
            set { keyword = value; }
        }
    }

    [Serializable]
    public class ExitData : IExitData
    {
        public LocationEdge ToLocationEdge(GeneralDirection dir, int x, int y, int z)
        {
            LocationEdge result = new LocationEdge()
            {
                Direction = dir,
                Vnum = this.vnum
            };

            if (d_info != null)
            {
                result.EdgeData = ((DoorData)d_info).CreateEdgeData();
            }

            result.Register();
            return result;
        }

        public ExitData() { }
        private int vnum;		/* VnumRoom this exit leads to */

        public int Vnum
        {
            get { return vnum; }
            set { vnum = value; }
        }
        [NonSerialized]
        private RoomData toRoomInternal = null;	/* Room data this exit leads to */

        public RoomData ToRoomInternal
        {
            get { return toRoomInternal; }
            set { toRoomInternal = value; }
        }
        private IDoorData d_info;	/* Optional door info structure */

        public IDoorData D_info
        {
            get { return d_info; }
            set { d_info = value; }
        }

        public RoomData to_room
        {
            get
            {
                if (toRoomInternal != null) return toRoomInternal;
                if (EmlenMud.WorldTemplates.htRooms.ContainsKey(vnum) == true)
                {
                    toRoomInternal = EmlenMud.WorldTemplates.htRooms[vnum];
                }
                else { toRoomInternal = null; }
                return toRoomInternal;
            }
            set
            {
                if (value == null) { toRoomInternal = null; vnum = 0; }
                else
                {
                    toRoomInternal = (RoomData)value;
                    vnum = value.VnumRoom;
                }
            }
        }

        public IExitData GetIncomingExitDataForDirection(GeneralDirection dir)
        {
            RoomData RoomTo = (RoomData)to_room;
            if (RoomTo == null) return null;
            GeneralDirection revdir = StaticHelpers.ReverseDirectionOf(dir);
            return RoomTo[revdir];
        }

        public void ResetExit(int dir) { ResetExit((GeneralDirection)dir); }
        public void ResetExit(GeneralDirection dir)
        {
            if (d_info != null)
            {
                if (d_info.IsDoor && d_info.Maxstr <= 0) { d_info.Str = 36; }
                if (d_info.Str < 0 && ((d_info.Rs_flags & ExitFlags.RESET) == 0))
                    return;

                d_info.Exit_info = d_info.Rs_flags;
                if (d_info.IsDoor && d_info.Maxstr > 0) { d_info.Str = d_info.Maxstr; }

                if (to_room != null)
                {
                    ExitData exrev = (ExitData)GetIncomingExitDataForDirection(dir);
                    if (exrev != null)
                    {
                        if (exrev.d_info != null)
                        {
                            exrev.d_info.Exit_info = exrev.d_info.Rs_flags;
                        }
                    }
                }
            }
        }
    }

    [Serializable]
    public class DoorData : GameThingBaseClass, IDoorData 
    {
        public EdgeData CreateEdgeData()
        {
            EdgeData result = new EdgeData()
            {
                DoorName = this.DoorName,
                ExitFlags = (int)this.Exit_info,
                ResetExitFlags = (int)this.Rs_flags,
                Key = this.Key,
                Keyword = this.Keyword,
                MaxStrength = this.Maxstr,
                CurrentStrength = this.Str,
                Description = this.Description
            };

            result.Register();
            return result;
        }

        public DoorData() { }
        public bool FlagSet(ExitFlags nBitfield, ExitFlags nFlag) { return ((nBitfield & nFlag) != 0); }
        public bool FlagSet(ExitFlags nFlag) { return ((exit_info & nFlag) != 0); }
        private ExitFlags exit_info;	/* Exit flags, mostly compat with diku */

        public ExitFlags Exit_info
        {
            get { return exit_info; }
            set { exit_info = value; }
        }
        private int key;		/* Key required to open the door */

        public int Key
        {
            get { return key; }
            set { key = value; }
        }
        private string keyword = "";	/* keyword for exit description */

        public string Keyword
        {
            get { return keyword; }
            set { keyword = value; }
        }
        private string description = "";	/* Exit description */

        public string Description
        {
            get { return description; }
            set { description = value; }
        }
        private int maxstr; /* Maximum door strength */

        public int Maxstr
        {
            get { return maxstr; }
            set { maxstr = value; }
        }
        private int str;	/* Door strength */

        public int Str
        {
            get { return str; }
            set { str = value; }
        }
        private ExitFlags rs_flags;	/* Reset Flags for doors, etc */

        public ExitFlags Rs_flags
        {
            get { return rs_flags; }
            set { rs_flags = value; }
        }
        public string DoorName
        {
            get { if (string.IsNullOrEmpty(this.ShortName)) return "door"; else return ShortName; }
        }
        public string StatusString()
        {
            if (FlagSet(ExitFlags.CLOSED)) return "closed";
            return "open";
        }
        public bool IsDoor
        {
            get { return ((rs_flags & ExitFlags.ISDOOR) != 0); }
            set
            {
                if ((rs_flags & ExitFlags.ISDOOR) == 0)
                {
                    if (value == true) { rs_flags |= ExitFlags.ISDOOR; }
                }
                else
                {
                    if (value == false) { rs_flags &= (~ExitFlags.ISDOOR); }
                }
            }
        }
    }

    [Serializable]
    public class ResetData : IResetData
    {
        public Reset ToReset()
        {
            Reset result = new Reset()
            {
                ApplyEffectLocation = loc,
                Command = command,
                Percent = percent,
                ResetVnum = rs_vnum,
                InRoomVnum = vnum
            };

            if (arg1 > 0)
                result.AddOrSetProperty("Arg1", arg1);

            if (arg2 > 0)
                result.AddOrSetProperty("Arg2", arg2);

            if (arg3 > 0)
                result.AddOrSetProperty("Arg3", arg3);

            result.Register();
            return result;
        }

        public ResetData() { }


        private char command;	/* command (Object Mob, etc) */

        public char Command
        {
            get { return command; }
            set { command = value; }
        }
        private int rs_vnum;	/* Reset vnumClan */

        public int Rs_vnum
        {
            get { return rs_vnum; }
            set { rs_vnum = value; }
        }
        private int loc;		/* ApplyEffectLocation or amount for shopkeeprs */

        public int Loc
        {
            get { return loc; }
            set { loc = value; }
        }
        private int percent;	/* Percent chance of pop */

        public int Percent
        {
            get { return percent; }
            set { percent = value; }
        }
        private int vnum;		/* VnumRoom it pops */

        public int Vnum
        {
            get { return vnum; }
            set { vnum = value; }
        }
        private int arg1;

        public int Arg1
        {
            get { return arg1; }
            set { arg1 = value; }
        }
        private int arg2;

        public int Arg2
        {
            get { return arg2; }
            set { arg2 = value; }
        }
        private int arg3;

        public int Arg3
        {
            get { return arg3; }
            set { arg3 = value; }
        }
    }
}
